package com.css.fxfzypg.modules.resultManagement.reportManagement.service.Impl;

import com.css.fxfzypg.modules.resultManagement.reportManagement.entity.ResultTable;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.Rows;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.RenderPolicy;
import com.deepoove.poi.render.compute.EnvModel;
import com.deepoove.poi.render.compute.RenderDataCompute;
import com.deepoove.poi.render.processor.DocumentProcessor;
import com.deepoove.poi.render.processor.EnvIterator;
import com.deepoove.poi.resolver.TemplateResolver;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.MetaTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.ReflectionUtils;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import org.springframework.util.CollectionUtils;
 
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
 
/**
 * @Description
 * @Author admin
 */
public class DefineMethodPolicy implements RenderPolicy {
    private String prefix;
    private String suffix;
    private boolean onSameLine;
 
    public DefineMethodPolicy() {
        this(false);
    }
 
    public DefineMethodPolicy(boolean onSameLine) {
        this("[", "]", onSameLine);
    }
 
    public DefineMethodPolicy(String prefix, String suffix) {
        this(prefix, suffix, false);
    }
 
    public DefineMethodPolicy(String prefix, String suffix, boolean onSameLine) {
        this.prefix = prefix;
        this.suffix = suffix;
        this.onSameLine = onSameLine;
    }
 
    @Override
    public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
        RunTemplate runTemplate = (RunTemplate) eleTemplate;
        XWPFRun run = runTemplate.getRun();
 
        try {
            if (!TableTools.isInsideTable(run)) {
                throw new IllegalStateException("The template tag " + runTemplate.getSource() + " must be inside a table");
            } else {
                XWPFTableCell tagCell = (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody();
                XWPFTable table = tagCell.getTableRow().getTable();
                run.setText("", 0);
                int templateRowIndex = this.getTemplateRowIndex(tagCell);
                if (null != data && data instanceof Iterable) {
                    Iterator<?> iterator = ((Iterable) data).iterator();
                    XWPFTableRow templateRow = table.getRow(templateRowIndex);
                    TemplateResolver resolver = new TemplateResolver(template.getConfig().copy(this.prefix, this.suffix));
                    boolean firstFlag = true;
                    int index = 0;
                    boolean hasNext = iterator.hasNext();

                    while (hasNext) {
                        Object root = iterator.next();
                        hasNext = iterator.hasNext();
                        int insertPosition = templateRowIndex++;
                        table.insertNewTableRow(insertPosition);
                        this.setTableRow(table, templateRow, insertPosition);
                        XmlCursor newCursor = templateRow.getCtRow().newCursor();
                        newCursor.toPrevSibling();
                        XmlObject object = newCursor.getObject();
                        XWPFTableRow nextRow = new XWPFTableRow((CTRow) object, table);
                        if (!firstFlag) {
                            List<XWPFTableCell> tableCells = nextRow.getTableCells();
                            Iterator var21 = tableCells.iterator();

                            while (var21.hasNext()) {
                                XWPFTableCell cell = (XWPFTableCell) var21.next();
                                CTTcPr tcPr = TableTools.getTcPr(cell);
                                CTVMerge vMerge = tcPr.getVMerge();
                                if (null != vMerge && STMerge.RESTART == vMerge.getVal()) {
                                    vMerge.setVal(STMerge.CONTINUE);
                                }
                            }
                        } else {
                            firstFlag = false;
                        }

                        this.setTableRow(table, nextRow, insertPosition);
                        RenderDataCompute dataCompute = template.getConfig().getRenderDataComputeFactory().
                                newCompute(EnvModel.of(root, EnvIterator.makeEnv(index++, hasNext)));
                        List<XWPFTableCell> cells = nextRow.getTableCells();
                        cells.forEach((cellx) -> {
                            List<MetaTemplate> templates = resolver.resolveBodyElements(cellx.getBodyElements());
                            (new DocumentProcessor(template, resolver, dataCompute)).process(templates);
                        });
                    }
                }

                table.removeRow(templateRowIndex);
                this.afterloop(table, data);
            }
        } catch (Exception var25) {
            throw new RenderException("HackLoopTable for " + eleTemplate + "error: " + var25.getMessage(), var25);
        }
    }
 
    private int getTemplateRowIndex(XWPFTableCell tagCell) {
        XWPFTableRow tagRow = tagCell.getTableRow();
        return this.onSameLine ? this.getRowIndex(tagRow) : this.getRowIndex(tagRow) + 1;
    }
 
    protected void afterloop(XWPFTable table, Object data) {
        if (null == data) {
            return;
        }
        List<ResultTable> defineMethodList = null;
        try {
            defineMethodList = (List<ResultTable>) data;
        } catch (Exception e) {
            e.printStackTrace();
        }
//        Map<String, List<ResultTable>> unitDefineMethodMap = defineMethodList.stream().collect(Collectors.groupingBy(ResultTable::getSort));
        Map<String, List<ResultTable>> unitParamMap = defineMethodList.stream().collect(Collectors.groupingBy(defineMethod -> defineMethod.getSort() + "-" + defineMethod.getLongitude()+"-"+defineMethod.getLatitude()+"-"+defineMethod.getMacroPosition()));
        if (!CollectionUtils.isEmpty(defineMethodList)) {
            List<RowRenderData> dataList = new ArrayList<>();
            for (ResultTable tmp : defineMethodList) {
//                RowRenderData renderData = Rows.create(tmp.getPoint(), tmp.getDevice(), tmp.getDeviceValue(), tmp.getValue().toString());
                RowRenderData renderData = Rows.create(tmp.getSort(),tmp.getLongitude(),tmp.getLatitude(),tmp.getMacroPosition(),tmp.getMagnitude().toString(),
                        tmp.getDisasterArea().toString(),tmp.getDisasterNum(),tmp.getDisasterGdp(),tmp.getDeathTollAfter(),tmp.getInjuredNumAfter(),tmp.getResettledNumAfter(),tmp.getRescueForceAfter(),tmp.getTentNumAfter());
                dataList.add(renderData);
            }
            List<String> unitList = null;
            try {
//                unitList = JacksonUtils.json2list(JacksonUtils.obj2json(unitDefineMethodMap.keySet()), String.class);
//                unitList = unitDefineMethodMap.keySet().stream().collect(Collectors.toList());

            } catch (Exception e) {
                e.printStackTrace();
            }
            List<String> paramList = null;
            try {
//                paramList = JacksonUtils.json2list(JacksonUtils.obj2json(unitParamMap.keySet()), String.class);
                paramList = unitParamMap.keySet().stream().collect(Collectors.toList());
            } catch (Exception e) {
                e.printStackTrace();
            }
            //处理合并
            for (int i = 0; i < dataList.size(); i++) {
                //处理第一列合并
                Object v = dataList.get(i).getCells().get(0).getParagraphs().get(0).getContents().get(0);
                Object v1 = dataList.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0);
                Object v2 = dataList.get(i).getCells().get(2).getParagraphs().get(0).getContents().get(0);
                Object v3 = dataList.get(i).getCells().get(3).getParagraphs().get(0).getContents().get(0);
                String unit_name = v+"-"+v1+"-"+v2+"-"+v3;
                for (int j = 0; j < paramList.size(); j++) {
                    String unitId = paramList.get(j);
                    List<ResultTable> patrolRecordReportVOS = unitParamMap.get(unitId);
                    String unitName = patrolRecordReportVOS.get(0).getSort() + "-" + patrolRecordReportVOS.get(0).getLongitude()+"-"+patrolRecordReportVOS.get(0).getLatitude()+"-"+patrolRecordReportVOS.get(0).getMacroPosition();
                    if (unit_name.equals(unitName) && patrolRecordReportVOS.size() > 1) {
                        // 合并第0列的第i+1行到第i+unitSize行的单元格
                        TableTools.mergeCellsVertically(table, 0, i + 2, i +1+ patrolRecordReportVOS.size());
                        TableTools.mergeCellsVertically(table, 1, i + 2, i +1+ patrolRecordReportVOS.size());
                        TableTools.mergeCellsVertically(table, 2, i + 2, i +1+ patrolRecordReportVOS.size());
                        TableTools.mergeCellsVertically(table, 3, i + 2, i +1+ patrolRecordReportVOS.size());
//                        TableTools.mergeCellsVertically(table, 4, i + 2, i + patrolRecordReportVOS.size());
                        //处理垂直居中
//                        for (int y = 0; y < 5; y++) {
//                            XWPFTableCell cell = table.getRow(i + 2).getCell(y);
//                            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); //垂直居中
//                        }
                        paramList.remove(j);
                        break;
                    }
                }
//                //处理第二列合并
//                Object v1 = dataList.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0);
//                String paramType = v + "-" + v1;
//                for (int j = 0; j < paramList.size(); j++) {
//                    String key = paramList.get(j);
//                    List<ResultTable> tmpList = unitParamMap.get(key);
//                    String paramName = tmpList.get(0).getSort() + "-" + tmpList.get(0).getLongitude();
//                    if (paramType.equals(paramName) && tmpList.size() > 1) {
//                        // 合并第1列的第i+1行到第i+unitSize行的单元格
//                        TableTools.mergeCellsVertically(table, 1, i + 2, i + tmpList.size());
//                        //处理垂直居中
//                        for (int y = 0; y < 5; y++) {
//                            XWPFTableCell cell = table.getRow(i + 2).getCell(y);
//                            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); //垂直居中
//                        }
//                        paramList.remove(j);
//                        break;
//                    }
//                }
            }
        }
    }
 
    private void setTableRow(XWPFTable table, XWPFTableRow templateRow, int pos) {
        List<XWPFTableRow> rows = (List) ReflectionUtils.getValue("tableRows", table);
        rows.set(pos, templateRow);
        table.getCTTbl().setTrArray(pos, templateRow.getCtRow());
    }
 
    private int getRowIndex(XWPFTableRow row) {
        List<XWPFTableRow> rows = row.getTable().getRows();
        return rows.indexOf(row);
    }
}